package com.library.management.repository;

import com.library.management.entity.User;
import com.library.management.enums.UserRole;
import com.library.management.enums.UserStatus;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * 用户数据访问层接口
 * 提供用户相关的数据库操作
 *
 * @author 开发者
 * @version 1.0
 * @since 2025-10-20
 */
@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    // ========== 基础查询方法 ==========

    /**
     * 根据用户名查找用户
     *
     * @param username 用户名
     * @return 用户对象
     */
    Optional<User> findByUsername(String username);

    /**
     * 根据邮箱查找用户
     *
     * @param email 邮箱地址
     * @return 用户对象
     */
    Optional<User> findByEmail(String email);

    /**
     * 根据用户名或邮箱查找用户
     *
     * @param username 用户名
     * @param email 邮箱地址
     * @return 用户对象
     */
    Optional<User> findByUsernameOrEmail(String username, String email);

    /**
     * 检查用户名是否存在
     *
     * @param username 用户名
     * @return true-存在，false-不存在
     */
    boolean existsByUsername(String username);

    /**
     * 检查邮箱是否存在
     *
     * @param email 邮箱地址
     * @return true-存在，false-不存在
     */
    boolean existsByEmail(String email);

    // ========== 角色和状态查询 ==========

    /**
     * 根据用户角色查找用户列表
     *
     * @param role 用户角色
     * @return 用户列表
     */
    List<User> findByRole(UserRole role);

    /**
     * 根据用户状态查找用户列表
     *
     * @param status 用户状态
     * @return 用户列表
     */
    List<User> findByStatus(UserStatus status);

    /**
     * 根据角色和状态查找用户
     *
     * @param role 用户角色
     * @param status 用户状态
     * @return 用户列表
     */
    List<User> findByRoleAndStatus(UserRole role, UserStatus status);

    /**
     * 分页查询指定角色的用户
     *
     * @param role 用户角色
     * @param pageable 分页参数
     * @return 分页用户数据
     */
    Page<User> findByRole(UserRole role, Pageable pageable);

    // ========== 复杂查询方法 ==========

    /**
     * 查找创建时间在指定范围内的用户
     *
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 用户列表
     */
    List<User> findByCreatedTimeBetween(LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 根据真实姓名模糊查询用户
     *
     * @param realName 真实姓名（模糊匹配）
     * @return 用户列表
     */
    List<User> findByRealNameContainingIgnoreCase(String realName);

    /**
     * 根据用户名或真实姓名模糊查询
     *
     * @param keyword 关键词
     * @return 用户列表
     */
    @Query("SELECT u FROM User u WHERE u.username LIKE %:keyword% OR u.realName LIKE %:keyword%")
    List<User> findByUsernameOrRealNameContaining(@Param("keyword") String keyword);

    /**
     * 统计指定角色的用户数量
     *
     * @param role 用户角色
     * @return 用户数量
     */
    long countByRole(UserRole role);

    /**
     * 统计指定状态的用户数量
     *
     * @param status 用户状态
     * @return 用户数量
     */
    long countByStatus(UserStatus status);

    // ========== 业务相关查询 ==========

    /**
     * 查找可以借书的活跃用户
     * 条件：状态为活跃，当前借阅数量小于最大借阅数量
     *
     * @return 可以借书的用户列表
     */
    @Query("SELECT u FROM User u WHERE u.status = 'ACTIVE' AND " +
            "(SELECT COUNT(br) FROM BorrowRecord br WHERE br.user = u AND br.status IN ('BORROWED', 'OVERDUE', 'RENEWED')) < u.maxBorrowCount")
    List<User> findUsersAvailableForBorrowing();

    /**
     * 查找有逾期罚款未支付的用户
     *
     * @return 有逾期罚款的用户列表
     */
    @Query("SELECT DISTINCT u FROM User u JOIN u.fines f WHERE f.status = 'UNPAID'")
    List<User> findUsersWithUnpaidFines();

    /**
     * 更新用户最后登录时间（示例方法，实际需要在User实体中添加lastLoginTime字段）
     */
    // @Modifying
    // @Query("UPDATE User u SET u.lastLoginTime = :loginTime WHERE u.id = :userId")
    // void updateLastLoginTime(@Param("userId") Long userId, @Param("loginTime") LocalDateTime loginTime);
    /**
     * 统计用户当前借阅数量
     */
    @Query("SELECT COUNT(br) FROM BorrowRecord br WHERE br.user.id = :userId AND br.status IN ('BORROWED', 'OVERDUE', 'RENEWED')")
    long countCurrentBorrowsByUserId(@Param("userId") Long userId);

    /**
     * 统计用户总借阅次数
     */
    @Query("SELECT COUNT(br) FROM BorrowRecord br WHERE br.user.id = :userId")
    long countByUserId(@Param("userId") Long userId);
}